package cn.virens.dd.execute;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.thread.ThreadUtil;

public class ExecuteWork<A, B> implements AutoCloseable {
	protected final ExecutorService executor;

	protected final Integer queueSize;
	protected final Integer queueMax;

	public ExecuteWork(Integer queueSize, Integer queueMax) {
		this.queueSize = Convert.toInt(queueSize, 100);
		this.queueMax = Convert.toInt(queueMax, 10);
		this.executor = ThreadUtil.newExecutor();
	}

	public List<Exception> execute(A param, Collection<B> collection) {
		int queueSize = calculateQueueSize(collection.size());

		// 将列表转为队列
		Queue<B> queue = buildQueue(collection.size(), collection);

		// 构建异步返回集
		List<Future<ExecuteResult>> futures = new ArrayList<>(queueSize);

		// 根据总共所需的线程池大小获取线程异步返回对象
		for (int i = 0; i < queueSize; i++) {
			futures.add(executor.submit(() -> {
				return execute0(param, queue);
			}));
		}

		// 等待获取全部线程异步返回值,并将异步返回的异常全部转移到一个列表中
		ExecuteResult result = new ExecuteResult();
		for (Future<ExecuteResult> future : futures) {
			result.execute(future, (temp) -> {
				return temp.get();
			});
		}

		return result;
	}

	protected ExecuteResult execute0(A param, Queue<B> queue) {
		return ExecuteResult.EMPTY;
	}

	protected Integer calculateQueueSize(double size) {
		double result = Math.ceil(size / queueMax);
		if (result > queueSize) return queueSize;

		return (int) result;
	}

	protected <T> Queue<T> buildQueue(Collection<T> collection) {
		return buildQueue(collection.size(), collection);
	}

	protected <T> Queue<T> buildQueue(int size, Collection<T> collection) {
		return new ArrayBlockingQueue<T>(size, false, collection);
	}

	@Override
	public void close() throws Exception {
		this.executor.shutdownNow();
	}
}
